use crate::{
    ascii::{spawn_ascii_sprite, AsciiSheet},
    tilemap::TileCollider,
    TILE_SIZE,
};
use bevy::{prelude::*, render::color::Color::Rgba, sprite::collide_aabb::collide};
use bevy_inspector_egui::Inspectable;
pub struct PlayerPlugin;


#[derive(Component, Inspectable)]
pub struct Player {
    pub speed: f32,
    pub position: Vec3,
}

// 玩家插件
impl Plugin for PlayerPlugin {
    fn build(&self, app: &mut App) {
        app.add_startup_system(spawn_player)
            .add_system(player_movement);
    }
}

// 玩家控制
fn player_movement(
    mut player_query: Query<(&mut Player, &mut Transform)>,
    wall_query: Query<&Transform, (With<TileCollider>, Without<Player>)>,
    keyboard: Res<Input<KeyCode>>,
    time: Res<Time>,
) {
    let (mut player, mut transform) = player_query.single_mut();

    let mut y_delta = 0.0;
    if keyboard.pressed(KeyCode::W) {
        y_delta += player.speed * TILE_SIZE * time.delta_seconds();
    }
    if keyboard.pressed(KeyCode::S) {
        y_delta -= player.speed * TILE_SIZE * time.delta_seconds();
    }

    let mut x_delta = 0.0;
    if keyboard.pressed(KeyCode::A) {
        x_delta -= player.speed * TILE_SIZE * time.delta_seconds();
    }
    if keyboard.pressed(KeyCode::D) {
        x_delta += player.speed * TILE_SIZE * time.delta_seconds();
    }
    
    let target = transform.translation + Vec3::new(x_delta, 0.0, 0.0);
    if !wall_query
        .iter()
        .any(|&transform| wall_collision_check(target, transform.translation))
    {
        transform.translation = target;
        player.position = transform.translation;
    }

    let target = transform.translation + Vec3::new(0.0, y_delta, 0.0);
    if !wall_query
        .iter()
        .any(|&transform| wall_collision_check(target, transform.translation))
    {
        transform.translation = target;
        player.position = transform.translation;
    }
}

fn wall_collision_check(target_player_pos: Vec3, wall_translation: Vec3) -> bool {
    let collision = collide(
        target_player_pos,
        Vec2::splat(TILE_SIZE * 0.9),
        wall_translation,
        Vec2::splat(TILE_SIZE),
    );
    collision.is_some()
}

fn spawn_player(mut commands: Commands, ascii: Res<AsciiSheet>) {
    let player = spawn_ascii_sprite(
        &mut commands,
        &ascii,
        1,
        Rgba {
            red: 0.3,
            green: 0.3,
            blue: 0.9,
            alpha: 0.9,
        },
        Vec3::new(1.0 * TILE_SIZE - 1.3, -1.0 * TILE_SIZE + 0.5, 600.0),
        Vec3::splat(1.0),
    );

    commands
        .entity(player)
        .insert(Name::new("Player"))
        .insert(Player { speed: 3.0, position: Vec3::new(1.0 * TILE_SIZE, -1.0 * TILE_SIZE, 0.0) });

    let background = spawn_ascii_sprite(
        &mut commands,
        &ascii,
        0,
        Rgba {
            red: 0.5,
            green: 0.5,
            blue: 0.5,
            alpha: 0.5,
        },
        Vec3::new(0.0, 0.0, -1.0),
        Vec3::splat(1.0),
    );

    commands.entity(background).insert(Name::new("Background"));
    commands.entity(player).push_children(&[background]);
}
